package org.whatever.aha.zjut.platform.aspect;

import lombok.RequiredArgsConstructor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.beetl.android.internal.util.ArrayUtils;
import org.springframework.stereotype.Component;
import org.whatever.aha.zjut.base.constant.ErrorCode;
import org.whatever.aha.zjut.base.constant.StatusConstant;
import org.whatever.aha.zjut.base.exception.AppException;
import org.whatever.aha.zjut.platform.annotation.StageLimit;
import org.whatever.aha.zjut.platform.dto.school.ProjectScoreDto;
import org.whatever.aha.zjut.platform.entity.competition.CompetitionStageStatus;
import org.whatever.aha.zjut.platform.service.competition.CompetitionService;
import org.whatever.aha.zjut.platform.service.competition.CompetitionStageStatusService;
import org.whatever.aha.zjut.platform.service.project.ProjectService;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author Vc
 * @version 1.0
 * @Desc
 * @date 2021/11/24 20:52
 */
@Aspect
@Component
@RequiredArgsConstructor
public class StageLimitAspect {
    final ProjectService projectService;
    final CompetitionStageStatusService competitionStageStatusService;
    final CompetitionService competitionService;

    @Pointcut("@annotation(stageLimit)")
    public void pointCut(StageLimit stageLimit) throws AppException {
    }

    @Before(value = "pointCut(stageLimit)", argNames = "joinpoint,stageLimit")
    public void before(JoinPoint joinpoint, StageLimit stageLimit) {
        MethodSignature methodSignature = (MethodSignature) joinpoint.getSignature();
        String[] parameterNames = methodSignature.getParameterNames();
        int stageIdx = ArrayUtils.indexOf(parameterNames, "stageId");
        int curStageId;
        //stageId信息不存在时取compId
        if (stageIdx == -1) {
            int compIdx = ArrayUtils.indexOf(parameterNames, "compId");
            //compId不存在报错
            if (compIdx == -1) {
                throw new AppException(ErrorCode.ANNOTATION_PARAM_ERROR);
            }
            int compId = (int) joinpoint.getArgs()[compIdx];
            //根据当前时间获取stageId
            curStageId = competitionService.getStageIdByTime(compId);
        }else {
            curStageId = (int) joinpoint.getArgs()[stageIdx];
        }




        //获取annotation的属性
        String[] values = methodSignature.getMethod().getAnnotation(StageLimit.class).value();
        List<CompetitionStageStatus> allowedCompetitionStageStatus = new ArrayList<>();
        for(String value : values){
            switch (value) {
                case "submit":
                    CompetitionStageStatus SubmitCompStageStatus = competitionStageStatusService.getSingleCompStageStatus(curStageId,  StatusConstant.COMPETITION_STAGE_STATUS_ORDER_SUBMIT.getCode());
                    allowedCompetitionStageStatus.add(SubmitCompStageStatus);
                    break;
                case "judge":
                    CompetitionStageStatus JudgeCompStageStatus = competitionStageStatusService.getSingleCompStageStatus(curStageId,  StatusConstant.COMPETITION_STAGE_STATUS_ORDER_JUDGE.getCode());
                    allowedCompetitionStageStatus.add(JudgeCompStageStatus);
                    break;
                case "public":
                    CompetitionStageStatus PublicCompStageStatus = competitionStageStatusService.getSingleCompStageStatus(curStageId,  StatusConstant.COMPETITION_STAGE_STATUS_ORDER_PROMULGATE.getCode());
                    allowedCompetitionStageStatus.add(PublicCompStageStatus);
                    break;
                 default:
                     throw new AppException(ErrorCode.ANNOTATION_PARAM_ERROR);
            }
        }

        //进行判断。不在允许操作的时间阶段内的操作报错
        Boolean flag = false;
        Date date = new Date();
        for(CompetitionStageStatus competitionStageStatus : allowedCompetitionStageStatus){
            if (date.before(competitionStageStatus.getStatusEndTime()) || date.after(competitionStageStatus.getStatusStartTime())) {
                flag = true;
                break;
            }
        }
        if (!flag) {
            throw new AppException(ErrorCode.TIME_CHECK_FAILED);
        }
    }
}
